package com.andromouse;

import java.awt.AWTException;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowStateListener;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.channels.FileLock;
import java.util.prefs.Preferences;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;

public class AndroMouse extends JFrame {
	public static JFrame f;
	static TrayIcon trayIcon = null;
	static JTabbedPane Tabs;
	/*private static BtHandler myBt;*/
	private static WifiHandler myWifi;
	static JLabel wifiAddress;
	static JButton startConnection;
	static JLabel status;
	static JLabel btName;
	JCheckBox passwordCheck;
	JPasswordField passwordText;
	private Preferences prefs;
	private boolean isMinimize;
	JTextField portField;
	JCheckBox minimizeCheck;

	public AndroMouse() {
		String operatingSystem = System.getProperty("os.name");
		if (operatingSystem.contains("Win")) {
			Utils.isWin = true;
			System.out.println("Running AndroMouse Server on "
					+ operatingSystem);
		}

		f = new JFrame("AndroMouse Server 2.5");
		f.setSize(300, 250);

		Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
		int w = f.getSize().width;
		int h = f.getSize().height;
		int x = (dim.width - w) / 2;
		int y = (dim.height - h) / 2;

		f.setLocation(x, y);

		f.setDefaultCloseOperation(3);

		this.prefs = Preferences.userRoot().node(getClass().getName());
		this.isMinimize = this.prefs.getBoolean("isMinimize", false);
		if (!this.isMinimize)
			f.setVisible(true);

		f.setResizable(false);

		Tabs = new JTabbedPane();
		f.add(Tabs, "Center");

		JPanel connectionPanel = new JPanel();
		connectionPanel.setLayout(new GridLayout(4, 2, 0, 0));
		JLabel jl1 = new JLabel("Your IP address: ");
		connectionPanel.add(jl1);
		wifiAddress = new JLabel("Address");
		connectionPanel.add(wifiAddress);
		JLabel jl3 = new JLabel("Bluetooth device: ");
		connectionPanel.add(jl3);
		btName = new JLabel("Bluetooth");
		connectionPanel.add(btName);
		JLabel st = new JLabel("Server status: ");
		connectionPanel.add(st);
		status = new JLabel("Open");
		connectionPanel.add(status);

		JLabel image1 = new JLabel();
		URL url = AndroMouse.class.getResource("images/server1.png");
		Image server = Toolkit.getDefaultToolkit().getImage(url);
		image1.setIcon(new ImageIcon(server));
		connectionPanel.add(image1);

		JLabel image2 = new JLabel();
		url = AndroMouse.class.getResource("images/server2.png");
		server = Toolkit.getDefaultToolkit().getImage(url);
		image2.setIcon(new ImageIcon(server));
		connectionPanel.add(image2);

		Tabs.add("Connections", connectionPanel);

		JPanel settingsPanel = new JPanel();
		settingsPanel.setLayout(new GridLayout(7, 1));
		this.passwordCheck = new JCheckBox("Enable password protection");
		this.passwordText = new JPasswordField(10);
		JLabel portNo = new JLabel(" TCP and UDP port number");
		this.portField = new JTextField("8888", 8);
		this.minimizeCheck = new JCheckBox(
				"Minimize window to system tray at startup");
		JButton applyBut = new JButton("Apply");
		applyBut.addActionListener(new ActionListener() {
			@SuppressWarnings("deprecation")
			public void actionPerformed(ActionEvent arg0) {
				int portNumber = Integer.parseInt(AndroMouse.this.portField
						.getText());
				AndroMouse.this.prefs.putInt("portnum", portNumber);

				AndroMouse.this.prefs.putBoolean("isPassword",
						AndroMouse.this.passwordCheck.isSelected());
				if (AndroMouse.this.passwordCheck.isSelected()) {
			//		@SuppressWarnings("deprecation")
					String p = AndroMouse.this.passwordText.getText();
					if (p.length() > 1) {
						AndroMouse.this.prefs.put("password", p);
					}
				}

				AndroMouse.this.prefs.putBoolean("isMinimize",
						AndroMouse.this.minimizeCheck.isSelected());
				Utils.isPassword = AndroMouse.this.passwordCheck.isSelected();
				Utils.password = AndroMouse.this.passwordText.getText();
				Utils.port = Integer.parseInt(AndroMouse.this.portField
						.getText());
			}
		});
		settingsPanel.add(this.passwordCheck);
		JPanel sp1 = new JPanel();
		sp1.setLayout(new FlowLayout(0));
		sp1.add(this.passwordText);
		settingsPanel.add(sp1);
		settingsPanel.add(portNo);
		JPanel sp2 = new JPanel();
		sp2.setLayout(new FlowLayout(0));
		sp2.add(this.portField);
		settingsPanel.add(sp2);
		JLabel spaceLab = new JLabel("");

		settingsPanel.add(this.minimizeCheck);
		settingsPanel.add(spaceLab);
		settingsPanel.add(applyBut);
		Tabs.add("Settings", settingsPanel);
		this.passwordCheck.setSelected(true);
		this.passwordCheck.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				AndroMouse.this.passwordText
						.setEnabled(AndroMouse.this.passwordCheck.isSelected());
			}
		});
		JPanel aboutPanel = new JPanel();
		aboutPanel.setLayout(new GridLayout(6, 1));
		JLabel nameLabel = new JLabel("AndroMouse Desktop Server");
		JLabel verLabel = new JLabel("Version 2.5");
		JLabel thankLabel = new JLabel("Thank you for using AndroMouse");
		JLabel likeLabel = new JLabel("If you like it please rate and comment");
		JLabel feedLabel = new JLabel("Send feedback to: info@iandrobot.net");
		aboutPanel.add(nameLabel);
		aboutPanel.add(verLabel);
		aboutPanel.add(thankLabel);
		aboutPanel.add(likeLabel);
		aboutPanel.add(feedLabel);
		JButton abt = new JButton("Visit AndroMouse.com");
		abt.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				AndroMouse.openSite();
			}
		});
		aboutPanel.add(abt);
		Tabs.add("About", aboutPanel);

		f.addWindowStateListener(new WindowStateListener() {
			public void windowStateChanged(WindowEvent arg0) {
				if (arg0.getNewState() == 1)
					AndroMouse.f.setVisible(false);
			}
		});
		pack();

		setupPref();
	}

	public static void main(String[] args) {
		new AndroMouse();
		sendToTray();
	}

	public static void sendToTray() {
		URL url = AndroMouse.class.getResource("images/mouse.png");

		Image image = Toolkit.getDefaultToolkit().getImage(url);
		f.setIconImage(image);

		if (!lockInstance("AMServer.temp")) {
			System.out.println("Instance not open");
			JOptionPane.showMessageDialog(f,
					"AndroMouse Server is already running");
			System.exit(0);
		}

		if (SystemTray.isSupported()) {
			SystemTray tray = SystemTray.getSystemTray();

			ActionListener Exitlistener = new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					System.exit(0);
				}
			};
			ActionListener listener = new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					AndroMouse.f.setVisible(true);
					AndroMouse.Tabs.setSelectedIndex(0);
				}
			};
			ActionListener aboutListener = new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					new AboutBox();
				}
			};
			ActionListener helpListener = new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					AndroMouse.openSite();
				}
			};
			ActionListener settingsListener = new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					AndroMouse.f.setVisible(true);
					AndroMouse.Tabs.setSelectedIndex(1);
				}
			};
			PopupMenu popup = new PopupMenu();

			MenuItem exitItem = new MenuItem("Exit");
			MenuItem aboutItem = new MenuItem("About AndroMouse");
			MenuItem helpItem = new MenuItem("Help");
			MenuItem openItem = new MenuItem("Restore");
			MenuItem settingsItem = new MenuItem("Settings");

			exitItem.addActionListener(Exitlistener);
			aboutItem.addActionListener(aboutListener);
			helpItem.addActionListener(helpListener);
			openItem.addActionListener(listener);
			settingsItem.addActionListener(settingsListener);

			popup.add(aboutItem);
			popup.add(openItem);
			popup.add(helpItem);
			popup.addSeparator();
			popup.add(settingsItem);
			popup.addSeparator();
			popup.add(exitItem);

			trayIcon = new TrayIcon(image, "AndroMouse Server", popup);
			trayIcon.addActionListener(listener);
			trayIcon.setImageAutoSize(true);
			try {
				tray.add(trayIcon);
			} catch (AWTException e) {
				System.err.println(e);
			}

			startWifiServer();
			//startBtServer();
		}
	}

	public static void trayMessage(String message) {
		trayIcon.displayMessage("AndroMouse Server", message,
				TrayIcon.MessageType.INFO);
	}

	public static void startWifiServer() {
		try {
			myWifi = new WifiHandler(wifiAddress, startConnection, trayIcon, status);
			myWifi.execute();
		} catch (Exception e) {
			System.out.println("Error wifihandler loader");
			e.printStackTrace();
		}
	}

	public static void startBtServer() {
		try {
			/*myBt = new BtHandler(btName, startConnection, trayIcon, status);
			myBt.execute();*/
		} catch (Exception e) {
			System.out.println("Error bthandler loader");
			e.printStackTrace();
		}
	}

	public static void openSite() {
		Desktop desktop = Desktop.getDesktop();
		try {
			URI uri = new URI("www.andromouse.com");
			desktop.browse(uri);
		} catch (URISyntaxException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}

	public void setupPref() {
		int port = this.prefs.getInt("portnum", 8888);

		System.out.println("Using port: " + port);

		boolean isMinimize = this.prefs.getBoolean("isMinimize", false);
		boolean isPassword = this.prefs.getBoolean("isPassword", false);
		String password = this.prefs.get("password", "");

		//this.portField.setText(port);
		this.minimizeCheck.setSelected(isMinimize);
		this.passwordCheck.setSelected(isPassword);
		this.passwordText.setText(password);
		this.passwordText.setEnabled(isPassword);

		Utils.isPassword = isPassword;
		Utils.password = password;
		Utils.port = port;
	}

	private static boolean lockInstance(String lockFile) {
		try {
			File file = new File(lockFile);
			RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
			FileLock fileLock = randomAccessFile.getChannel().tryLock();
			if (fileLock != null) {
				/*Runtime.getRuntime().addShutdownHook(
						new Thread(fileLock, randomAccessFile, file, lockFile) {
							public void run() {
								try {
									AndroMouse.this.release();
									this.val$randomAccessFile.close();
									this.val$file.delete();
								} catch (Exception e) {
									System.out
											.println("Unable to remove lock file: "
													+ this.val$lockFile);
								}
							}
						});*/
				return true;
			}
		} catch (Exception e) {
			System.out
					.println("Unable to create and/or lock file: " + lockFile);
		}
		return false;
	}
}
